﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////


#include "GnufFilledRegionParameterDisplay.h"
#include "IParameterValueString.h"
#include "IElement.h"
#include "IGenericElement.h"
#include "IElementParameters.h"
#include "GnufToolbar.h"
#include "GnufPushButton.h"
#include "QApplication"
#include "GnufItem.h"
#include "QDesktopWidget"
#include "GnufQtButtonEx.h"
#include "GnufNameValuePairs.h"
#include "GnufFilledRegionBoard.h"
#include "GnufParameterDisplayCustomFactory.h"
#include "IFamilyFillPatternManager.h"
#include "IParameterDefinitionLibrary.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "IFillPattern.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace gnuf;
using namespace gfam;

gnuf::Item * gfam::FilledRegionParameterPatternDisplay::OnDisplay(gnuf::NameValuePairBlock * pNameValuePairBlock, gcmp::IElement * pElement, int parameterId)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pNameValuePairBlock, L"pNameValuePairBlock为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElement, L"pElement为空", L"paramodel", L"2024-02-20");

    IDocument* pDoc = pElement->GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空", L"paramodel", L"2024-02-20");

    m_doc = pDoc;
    IElementParameters* pParams = pElement->GetElementParameters();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pParams, L"pParams为空", L"paramodel", L"2024-02-20");

    OwnerPtr<IParameter> opParam = pParams->GetParameterById(parameterId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opParam, L"opParam为空", L"paramodel", L"2024-02-20");
    if (opParam->GetParameterDefinitionUid() == PARAMETER_UID(FamilyFilledRegionPatternBuiltInParameter))
    {
        std::wstring strCurrentPatten = opParam->GetValueAsString();
        if (strCurrentPatten == L"SOLID")
        {
            strCurrentPatten = L"实体填充";
        }
        IFamilyFillPatternManager * pManager = IFamilyFillPatternManager::Get(m_doc);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pManager != nullptr, L"pManager为空", L"paramodel", L"2024-02-20");
        std::vector<const IFillPattern*> fillPatternDatas = pManager->GetAllFillPatterns();
        const IFillPattern* currPatternDatas = nullptr;

        FOR_EACH_INDEX(i, fillPatternDatas)
        {
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(fillPatternDatas[i] != nullptr, L"pPattern为空", L"paramodel", L"2024-02-20");
            const IGenericElement* pHatchPatternEle = quick_cast<const IGenericElement>(fillPatternDatas[i]->GetOwnerElement());
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pHatchPatternEle, L"pHatchPatternEle为空", L"paramodel", L"2024-02-20");
            const IFillPattern* pHatchPatternObject = quick_cast<IFillPattern>(pHatchPatternEle->GetExternalObject());
            if (pHatchPatternObject->GetName().compare(strCurrentPatten) == 0) currPatternDatas = pHatchPatternObject;
        }
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pNameValuePairBlock != nullptr && pNameValuePairBlock->root() != nullptr, L"pToolbar为空", L"paramodel", L"2024-02-20");
        Toolbar* pToolbar = pNameValuePairBlock->root()->cast<Toolbar>();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pToolbar, L"pToolbar为空", L"paramodel", L"2024-02-20");

        pToolbar->tweakAppearanceSetting([](AppearanceSetting* pAppearanceSetting) -> void {
            if (pAppearanceSetting)
            {
                ButtonAppearanceSetting* pBtnAppearanceSetting = pAppearanceSetting->buttonAppearanceSetting();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pBtnAppearanceSetting, L"pBtnAppearanceSetting为空", L"paramodel", L"2024-02-20");

                pBtnAppearanceSetting->setIconSize(EIconSize::e24x24);
                pBtnAppearanceSetting->setPadding({ 12, 4, 12, 4 });
                pBtnAppearanceSetting->setSpacing(6);
                pBtnAppearanceSetting->setHoverColor(gnuf::Color::fromCode(ColorCode::Input01));
            }});

        if (currPatternDatas == nullptr)
        {
            currPatternDatas = fillPatternDatas.at(0);
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(currPatternDatas != nullptr, L"pPattern为空", L"paramodel", L"2024-02-20");
            strCurrentPatten = currPatternDatas->GetName();
        }

        m_pComboButton = pNameValuePairBlock->addItem<gnuf::PushButton>(gnuf::Info(opParam->GetName()));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_pComboButton, L"m_pComboButton为空", L"paramodel", L"2024-02-20");

        m_pComboButton->assignInfo(Info(strCurrentPatten), GnufFilledPatternBoard::generatePixmapByteArray(currPatternDatas->GetFillPatternData(), { 24,16 }));

        m_filledPatternBoard = GnufFilledPatternBoard::getInstance();
        m_filledPatternBoard->setCurrentPattern(strCurrentPatten);
        m_filledPatternBoard->setMaximumColumn(3);
        m_filledPatternBoard->setReference(m_pComboButton);

        if (nullptr == m_buttonControl.get())
        {
            m_buttonControl = NEW_AS_OWNER_PTR(ButtonControl, this, NEW_AS_OWNER_PTR(gnuf::Info, opParam->GetName()), NEW_AS_OWNER_PTR(gnuf::Info, opParam->GetName()));
        }
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_buttonControl, L"m_buttonControl为空", L"paramodel", L"2024-02-20");
        m_buttonControl->subscribe(m_pComboButton);
        const IParameterValueStorage* pParamStorage = opParam->GetParameterValueStorage();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pParamStorage, L"pParamStorage为空", L"paramodel", L"2024-02-20");
        m_currentValue = TransferOwnershipCast<IParameterValueString>(pParamStorage->Clone());
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_currentValue, L"m_currentValue为空", L"paramodel", L"2024-02-20");
        m_currentValue->SetValue(strCurrentPatten);
    }

    return m_pComboButton;
}

gnuf::Item * gfam::FilledRegionParameterPatternDisplay::OnDisplay(gnuf::NameValuePairBlock * pNameValuePairBlock, const std::vector<gcmp::IElement*>& elements, int parameterId)
{
    return nullptr;
}

void gfam::FilledRegionParameterPatternDisplay::onClicked()
{
    IFamilyFillPatternManager * pManager = IFamilyFillPatternManager::Get(m_doc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pManager != nullptr, L"pManager为空", L"paramodel", L"2024-02-20");
    std::vector<const IFillPattern*> fillPatternDatas = pManager->GetAllFillPatterns();
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_filledPatternBoard, L"m_filledPatternBoard为空", L"paramodel", L"2024-02-20");
    m_filledPatternBoard->setPatternDatas(pManager->GetAllFillPatterns());

    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pComboButton, L"m_pComboButton为空", L"paramodel", L"2024-02-20");
    auto item = m_pComboButton->qtItem();
    DBG_WARN_AND_RETURN_VOID_UNLESS(item, L"item为空", L"paramodel", L"2024-02-20");
    QWidget* pReferenceWidget = item->castQWidget();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pReferenceWidget, L"pReferenceWidget为空", L"paramodel", L"2024-02-20");

    QPoint below = pReferenceWidget->mapToGlobal(pReferenceWidget->rect().bottomLeft());
    QDesktopWidget *qDesktopWidget = QApplication::desktop();
    DBG_WARN_AND_RETURN_VOID_UNLESS(qDesktopWidget, L"qDesktopWidget为空", L"paramodel", L"2024-02-20");
    QRect screenGeometry = qDesktopWidget->screenGeometry(qDesktopWidget->screenNumber(pReferenceWidget));

    // 以避免填充样式菜单的底部顶到屏幕底部
    int tolerance = 40;
    int belowHeight = screenGeometry.bottom() - below.y() - tolerance;
    m_filledPatternBoard->setReferencePosition(GnufFilledPatternBoard::EReferencePosition::eLeftBottom);
    if (belowHeight < 252)
    {
        QPoint top = pReferenceWidget->mapToGlobal(pReferenceWidget->rect().topLeft());
        belowHeight = top.y();
        m_filledPatternBoard->setReferencePosition(GnufFilledPatternBoard::EReferencePosition::eLeftTop);
    }
    m_filledPatternBoard->setHeight(belowHeight);
    m_filledPatternBoard->build();
    m_filledPatternBoard->exec();

    m_pComboButton->assignInfo(Info(m_filledPatternBoard->getSelectedPatternName()),
        GnufFilledPatternBoard::generatePixmapByteArray(m_filledPatternBoard->getSelectedPatternData(), { 24,16 }));
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_currentValue, L"m_currentValue为空", L"paramodel", L"2024-02-20");
    m_currentValue->SetValue(m_filledPatternBoard->getSelectedPatternName());
}

bool gfam::FilledRegionParameterPatternDisplay::onSupportToSelect() const
{
    return false;
}
gcmp::OwnerPtr<gcmp::IParameterValueStorage> gfam::FilledRegionParameterPatternDisplay::GetValue(gcmp::IDocument * pDoc, const std::vector<gcmp::ElementId>& elements, const gnuf::Item * pItem) const
{
    return m_currentValue ? m_currentValue->Clone() : IParameterValueString::Create(L"");
}

GnufParameterDisplayCustomCreator s_filledRegionParameterPatternDisplayCreator(PARAMETER_UID(FamilyFilledRegionPatternBuiltInParameter), NEW_AS_OWNER_PTR(FilledRegionParameterPatternDisplay));